#ifndef _SYS_LOG_H
#define _SYS_LOG_H

#if defined(__cplusplus)
extern "C" {
#endif

#include <string.h>
#include <stdint.h>

#define SYS_DBG_BUF_LEN 2048 // 512
#ifdef HOST_COMPILER_LINUX
#define filename(x) strrchr(x, '\\') ? strrchr(x, '\\') + 1 : x
#else
#define filename(x) strrchr(x, '/') ? strrchr(x, '/') + 1 : x
#endif

#ifndef __DEFINE_MODELE_NAME__
#define __DEFINE_MODELE_NAME__ filename(__FILE__)
#define _DISPLAY_FILE_(x)      x
#else
#define _DISPLAY_FILE_(x) filename(x)
#endif

#ifndef _LOG_MEMOUT
#define _LOG_MEMOUT "memout"
#endif

#ifndef NULL
#define NULL 0
#endif

extern char *get_task_id(void);
#define TASK_ID get_task_id()

typedef enum
{
    SYS_LOG_LEVEL_OFF   = 0x0,  // OFF Level
    SYS_LOG_LEVEL_ERROR = 0x1,  // ERROR level
    SYS_LOG_LEVEL_WARN  = 0x2,  // WARN level
    SYS_LOG_LEVEL_INFO  = 0x3,  // INFO level
    SYS_LOG_LEVEL_DEBUG = 0x4,  // DEBUG Level
    SYS_LOG_LEVEL_ALL   = 0xFF, // ALL Level
} sys_log_e;

typedef enum
{
    SYS_LOG_NORMAL_NEVER_SAVE_MODE = 0x0, // never save log in lfs
    SYS_LOG_NORMAL_TERM_SAVE_MODE,        // term save mode  use sys_stolog_set_level config
    SYS_LOG_ISR_OUT_MODE,                 // ISR log out
    SYS_LOG_FORMAT_OUT_MODE_MAX,          // syslog max num
    SYS_LOG_DIREAT_PUTOUT_MODE            // no utc and filename and direct printf
} sys_log_mode_e;

#ifndef DLOG_LEVEL
#define DLOG_LEVEL 5
#endif

#if DLOG_LEVEL == 1
#define DLOG_D(format, ...)
#define DLOG_W(format, ...)
#define DLOG_E(format, ...)
#define DLOG_I(format, ...)
#elif DLOG_LEVEL == 2
#define DLOG_I(format, ...)
#define DLOG_D(format, ...)
#define DLOG_W(format, ...)
#elif DLOG_LEVEL == 3
#define DLOG_D(format, ...)
#define DLOG_W(format, ...)
#elif DLOG_LEVEL == 4
#define DLOG_D(format, ...)
#endif

#define NOT_DISABLE_SLOG
#ifndef NOT_DISABLE_SLOG
#define SLOG_I(format, ...)
#define SLOG_D(format, ...)
#define SLOG_E(format, ...)
#define SLOG_W(format, ...)
#define DLOG_I(format, ...)
#define DLOG_D(format, ...)
#define DLOG_E(format, ...)
#define DLOG_W(format, ...)
#define SLOG_INT(format, ...)
#define SLOG_STDOUT(format, ...)
#define SLOG_LINE_X(format, ...)
#define SLOG_LINE_C(format, ...)
#endif

#ifndef THIS_MODULE

int sys_log_core(const char *module, int info, int line, const char *fmt, ...);
int show_xxx_port_great(char *s, uint8_t *buf, int size, char *mode);

#ifndef DLOG_D
#define DLOG_D(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_DEBUG, __LINE__, ##__VA_ARGS__)
#endif

#ifndef DLOG_E
#define DLOG_E(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_ERROR, __LINE__, ##__VA_ARGS__)
#endif

#ifndef DLOG_W
#define DLOG_W(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_WARN, __LINE__, ##__VA_ARGS__)
#endif

#ifndef DLOG_I
#define DLOG_I(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_INFO, __LINE__, ##__VA_ARGS__)
#endif

#ifndef SLOG_D
#define SLOG_D(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_DEBUG, __LINE__, ##__VA_ARGS__)
#endif

#ifndef SLOG_E
#define SLOG_E(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_ERROR, __LINE__, ##__VA_ARGS__)
#endif

#ifndef SLOG_W
#define SLOG_W(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_WARN, __LINE__, ##__VA_ARGS__)
#endif

#ifndef SLOG_I
#define SLOG_I(...) sys_log_core(__DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_INFO, __LINE__, ##__VA_ARGS__)
#endif

#ifndef SLOG_INT // ISR log
#define SLOG_INIT(...) sys_log_core(SYS_LOG_ISR_OUT_MODE, __DEFINE_MODELE_NAME__, SYS_LOG_LEVEL_DEBUG, __LINE__, ##__VA_ARGS__)
#endif

#ifndef SLOG_STDOUT
#define SLOG_STDOUT(...) // xil_printf(__VA_ARGS__)
#endif

#ifndef SLOG_LINE_X
#define SLOG_LINE_X(A, B, C) show_xxx_port_great((char *)A, (uint8_t *)B, C, "%02x")
#endif

#ifndef SLOG_LINE_C
#define SLOG_LINE_C(A, B, C) show_xxx_port_great((char *)A, (uint8_t *)B, C, "%c")
#endif

int sys_log_get_level(void);
int sys_log_set_level(int level);

#endif

#if defined(__cplusplus)
}
#endif

#endif /* _SYS_LOG_H */
